package com.david.config.config;

import com.david.config.task.IPollableService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Configuration
@EnableAsync
@EnableScheduling
//@Slf4j
public class SchedulingConfiguration implements SchedulingConfigurer, ApplicationContextAware {
    private static final Logger log = LoggerFactory.getLogger(SchedulingConfiguration.class);

    private static ApplicationContext appCtx;
    private final ConcurrentMap<String, ScheduledTask> scheduledTaskHolder = new ConcurrentHashMap<>(16);
    private final ConcurrentMap<String, String> cronExpressionHolder = new ConcurrentHashMap<>(16);
    private ScheduledTaskRegistrar taskRegistrar;
    public static synchronized void setAppCtx(ApplicationContext appCtx) {
        SchedulingConfiguration.appCtx = appCtx;
    }



    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        setAppCtx(applicationContext);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        this.taskRegistrar = taskRegistrar;
    }

    /**
    * @Description: cronExpression为”-“时，任务停止
    * @Param: []
    * @return: void
    * @Author: david
    * @Date: 2024/9/3
    */
    public void refresh() {
        Map<String, IPollableService> beanMap = appCtx.getBeansOfType(IPollableService.class);
        if (beanMap.isEmpty() || taskRegistrar == null){
            return;
        }
        beanMap.forEach((beanName, task) -> {
            String expression = task.getCronExpression();
            String taskName = task.getTaskName();
            if (null == expression) {
                log.warn("定时任务[{}]未配置cron表达式，跳过", taskName);
                return;
            }
            boolean unmodified = scheduledTaskHolder.containsKey(beanName) && cronExpressionHolder.get(beanName).equals(expression);
            if (unmodified) {
                log.info("定时任务[{}]未修改，跳过", taskName);
                return;
            }
            Optional.ofNullable(scheduledTaskHolder.remove(beanName)).ifPresent(existTask -> {
                existTask.cancel();
                cronExpressionHolder.remove(beanName);
            });
            if (ScheduledTaskRegistrar.CRON_DISABLED.equals(expression)){
                log.warn("定时任务[{}]已禁用", taskName);
                return;
            }
            CronTask cronTask = new CronTask(task::poll, expression);
            ScheduledTask scheduledTask = taskRegistrar.scheduleCronTask(cronTask);
            if (scheduledTask != null){
                log.info("定时任务[{}]已更新", taskName);
                scheduledTaskHolder.put(beanName, scheduledTask);
                cronExpressionHolder.put(beanName, expression);
            }
        });
    }



    //    @Bean
//    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
//        log.info("初始化定时任务线程池 start");
//        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
//        scheduler.setPoolSize(10);
//        scheduler.setThreadNamePrefix("scheduled-task-");
//        scheduler.setWaitForTasksToCompleteOnShutdown(true);
//        scheduler.setAwaitTerminationSeconds(60);
//        log.info("初始化定时任务线程池 end");
//        return scheduler;
//    }

}
